/*
 * Copyright 2016-2022 The OSHI Project Contributors
 * SPDX-License-Identifier: MIT
 */
package oshi.hardware.common;

import static oshi.util.Memoizer.defaultExpiration;
import static oshi.util.Memoizer.memoize;

import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

import oshi.annotation.concurrent.ThreadSafe;
import oshi.hardware.SensorFanInfo;
import oshi.hardware.GpuInfo;
import oshi.hardware.Sensors;

/**
 * Sensors from WMI or Open Hardware Monitor or Libre Hardware Monitor
 */
@ThreadSafe
public abstract class AbstractSensors implements Sensors {

    private final Supplier<Double> cpuTemperature = memoize(this::queryCpuTemperature, defaultExpiration());

    private final Supplier<int[]> fanSpeeds = memoize(this::queryFanSpeeds, defaultExpiration());

    private final Supplier<Double> cpuVoltage = memoize(this::queryCpuVoltage, defaultExpiration());

    private final Supplier<List<SensorFanInfo>> motherBoardFan = memoize(this::queryMotherboardFans, defaultExpiration());
    private final Supplier<List<SensorFanInfo>> gpuFan = memoize(this::queryGpuFans, defaultExpiration());

    private final Supplier<List<GpuInfo>> gpuInfos = memoize(this::queryGpuInfos, defaultExpiration());


    @Override
    public double getCpuTemperature() {
        return cpuTemperature.get();
    }

    protected abstract double queryCpuTemperature();

    @Override
    public int[] getFanSpeeds() {
        return fanSpeeds.get();
    }

    protected abstract int[] queryFanSpeeds();

    @Override
    public double getCpuVoltage() {
        return cpuVoltage.get();
    }

    protected abstract double queryCpuVoltage();

    @Override
    public List<SensorFanInfo> getMotherboardFans() {
        return motherBoardFan.get();
    }

    protected abstract List<SensorFanInfo> queryMotherboardFans();

    @Override
    public List<SensorFanInfo> getGraphicsCardFans() {
        return gpuFan.get();
    }
    protected abstract List<SensorFanInfo> queryGpuFans();

    @Override
    public List<GpuInfo> getGpuInfos() {
        return gpuInfos.get();
    }

    protected abstract List<GpuInfo> queryGpuInfos();


    @Override
    public String toString() {
        // TODO: 其他硬件信息
        StringBuilder sb = new StringBuilder();
        sb.append("CPU Temperature=").append(getCpuTemperature()).append("C, ");
        sb.append("Fan Speeds=").append(Arrays.toString(getFanSpeeds())).append(", ");
        sb.append("CPU Voltage=").append(getCpuVoltage()).append(", ");
        sb.append("MotherBoard Fans=").append(getMotherboardFans());
        return sb.toString();
    }
}
